Introduction

SCPNext provides a comprehensive set of tools for single-cell data processing and downstream analysis. It is developed on the basis of SCP (Single-Cell Pipeline), but with full support for Seurat V5 and later, and enhanced python package management using uv.

Installation

Prerequisites

You will need uv for managing the Python environment. To install, run the following command in your terminal:

# On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh
# On Windows.
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Or from PyPI:

# With pip.
pip install uv
# Or pipx.
pipx install uv

R version requirement

  • R>4.1.0
  • Seurat>4.1.0

Install from GitHub

# Install devtools if needed
install.packages("devtools")

# Install SCPNext
devtools::install_github("mianaz/SCP-SeuratV5")

Python Environment Setup (One-Time Only)

To speed up and simplify the installation of Python dependencies, SCPNext uses uv to create and manage a dedicated Python environment.

library(SCPNext)

# Option 1: Basic installation (recommended) - ~30 seconds
# Essential single-cell tools for standard analysis
PrepareEnv(extras = "basic", force=TRUE)

# Option 2: Full installation - ~90 seconds
# Includes velocity, trajectory, deep learning, machine learning
PrepareEnv(extras = "all", force=TRUE)

In future R sessions, run:

use_uv_env()  # Activate Python environment

Quick Start

Data Exploration

#library(BiocParallel)
#register(MulticoreParam(workers = 8, progressbar = TRUE))

data("pancreas_sub")
print(pancreas_sub)
#> An object of class Seurat 
#> 47874 features across 1000 samples within 3 assays 
#> Active assay: RNA (15958 features, 3467 variable features)
#>  2 layers present: counts, data
#>  2 other assays present: spliced, unspliced
#>  2 dimensional reductions calculated: PCA, UMAP
CellDimPlot(
  srt = pancreas_sub, group.by = c("CellType", "SubCellType"),
  reduction = "UMAP", theme_use = "theme_blank"
)

CellDimPlot(
  srt = pancreas_sub, group.by = "SubCellType", stat.by = "Phase",
  reduction = "UMAP", theme_use = "theme_blank"
)

FeatureDimPlot(
  srt = pancreas_sub, features = c("Sox9", "Neurog3", "Fev", "Rbp4"),
  reduction = "UMAP", theme_use = "theme_blank"
)

FeatureDimPlot(
  srt = pancreas_sub, features = c("Ins1", "Gcg", "Sst", "Ghrl"),
  compare_features = TRUE, label = TRUE, label_insitu = TRUE,
  reduction = "UMAP", theme_use = "theme_blank"
)

ht <- GroupHeatmap(
  srt = pancreas_sub,
  features = c(
    "Sox9", "Anxa2", # Ductal
    "Neurog3", "Hes6", # EPs
    "Fev", "Neurod1", # Pre-endocrine
    "Rbp4", "Pyy", # Endocrine
    "Ins1", "Gcg", "Sst", "Ghrl" # Beta, Alpha, Delta, Epsilon
  ),
  group.by = c("CellType", "SubCellType"),
  heatmap_palette = "YlOrRd",
  cell_annotation = c("Phase", "G2M_score", "Cdh2"),
  cell_annotation_palette = c("Dark2", "Paired", "Paired"),
  show_row_names = TRUE, row_names_side = "left",
  add_dot = TRUE, add_reticle = TRUE
)
print(ht$grob)

CellQC

pancreas_sub <- RunCellQC(srt = pancreas_sub)
#> >>> Total cells: 1000 
#> >>> Cells which are filtered out: 46 
#> ... 32 potential doublets 
#> ... 14 outlier cells 
#> ... 0 low-UMI cells 
#> ... 0 low-gene cells 
#> ... 0 high-mito cells 
#> ... 0 high-ribo cells 
#> ... 0 ribo_mito_ratio outlier cells 
#> ... 0 species-contaminated cells 
#> >>> Remained cells after filtering: 954
CellDimPlot(srt = pancreas_sub, group.by = "CellQC", reduction = "UMAP")

CellStatPlot(srt = pancreas_sub, stat.by = "CellQC", group.by = "CellType", label = TRUE)

CellStatPlot(
  srt = pancreas_sub,
  stat.by = c(
    "db_qc", "outlier_qc", "umi_qc", "gene_qc",
    "mito_qc", "ribo_qc", "ribo_mito_ratio_qc", "species_qc"
  ),
  plot_type = "upset", stat_level = "Fail"
)

Standard Pipeline

# needs to add timestamp
pancreas_sub <- Standard_SCP(srt = pancreas_sub)
#> [2025-10-23 00:01:55.127048] Starting Standard_SCP...
#> [2025-10-23 00:01:55.127563] Checking input...
#> [2025-10-23 00:01:55.151193] Processing single object...
#> [2025-10-23 00:01:55.183293] Normalizing data (LogNormalize)...
#> [2025-10-23 00:01:55.654189] Finding variable features...
#> [2025-10-23 00:01:56.227863] Found 2000 variable features
#> [2025-10-23 00:01:56.241902] Scaling data...
#> [2025-10-23 00:01:56.29333] Running dimension reduction (pca)...
#> [2025-10-23 00:02:11.346593] Finding clusters (louvain)...
#> [2025-10-23 00:02:11.385657] Reordering clusters...
#> [2025-10-23 00:02:11.420484] Computing UMAP embedding...
#> [2025-10-23 00:02:14.790617] Standard_SCP completed in 19.66 secs
CellDimPlot(
  srt = pancreas_sub, group.by = c("CellType", "SubCellType"),
  reduction = "StandardUMAP2D", theme_use = "theme_blank"
)

CellDimPlot3D(srt = pancreas_sub, group.by = "SubCellType")
FeatureDimPlot3D(srt = pancreas_sub, features = c("Sox9", "Neurog3", "Fev", "Rbp4"))

Integration Pipeline

# needs to be tested separately
data("panc8_sub")
panc8_sub <- Integration_SCP(srtMerge = panc8_sub, batch = "tech", integration_method = "Seurat")
#> [2025-10-23 00:02:15.651521] Start Seurat_integrate (v5_layers workflow)
#> [2025-10-23 00:02:15.651814] Using Seurat v5 layers-based workflow (auto-detected)...
#> [2025-10-23 00:02:15.744419] Splitting layers by batch: tech...
#> [2025-10-23 00:02:15.913942] Normalizing data (LogNormalize) across layers...
#> [2025-10-23 00:02:16.568765] Finding variable features across layers...
#> [2025-10-23 00:02:18.167651] Scaling data across layers (optimized)...
#> [2025-10-23 00:02:18.167651]   Scaling 2000 variable features across 5 split layers...
#> [2025-10-23 00:02:18.167651]   Number of cells: 1600
#> [2025-10-23 00:02:18.285623]   ScaleData completed in 0.12 seconds
#> [2025-10-23 00:02:18.28574] Running PCA on the merged object...
#> [2025-10-23 00:02:19.086008] Performing integration using CCAIntegration...
#> [2025-10-23 00:02:27.863951] Finding neighbors on integrated.dr...
#> [2025-10-23 00:02:28.59454] Finding clusters (louvain)...
#> [2025-10-23 00:02:28.664311] Reordering clusters...
#> [2025-10-23 00:02:28.711772] Computing UMAP (2D) on integrated.dr...
#> [2025-10-23 00:02:31.555267] Computing UMAP (3D) on integrated.dr...
#> [2025-10-23 00:02:34.484805] Joining layers after downstream analysis...
#> [2025-10-23 00:02:34.900412] Seurat_integrate done
#> Elapsed time: 19.25 secs
CellDimPlot(
  srt = panc8_sub, group.by = c("celltype", "tech"), reduction = "SeuratUMAP2D",
  title = "Seurat", theme_use = "theme_blank"
)

Cell projection between single-cell datasets

# human to mouse (demo purpose only, please consider ortholog mapping for real cases)
new.names<- make.unique(capitalize(rownames(panc8_sub[["RNA"]]), force_tolower = TRUE))
panc8_rename <- panc8_sub
rownames(panc8_rename[["RNA"]]) <- new.names
srt_query <- RunKNNMap(srt_query = pancreas_sub, srt_ref = panc8_rename, ref_umap = "SeuratUMAP2D")
ProjectionPlot(
  srt_query = srt_query, srt_ref = panc8_rename,
  query_group = "SubCellType", ref_group = "celltype"
)

Cell annotation using bulk RNA-seq datasets

data("ref_scMCA")
pancreas_sub <- RunKNNPredict(srt_query = pancreas_sub, bulk_ref = ref_scMCA, filter_lowfreq = 20)
CellDimPlot(srt = pancreas_sub, group.by = "KNNPredict_classification", reduction = "UMAP", label = TRUE)

Cell annotation using single-cell datasets

pancreas_sub <- RunKNNPredict(
  srt_query = pancreas_sub, srt_ref = panc8_rename,
  ref_group = "celltype", filter_lowfreq = 20
)
CellDimPlot(srt = pancreas_sub, group.by = "KNNPredict_classification", reduction = "UMAP", label = TRUE)

pancreas_sub <- RunKNNPredict(
  srt_query = pancreas_sub, srt_ref = panc8_rename,
  query_group = "SubCellType", ref_group = "celltype",
  return_full_distance_matrix = TRUE
)
CellDimPlot(srt = pancreas_sub, group.by = "KNNPredict_classification", reduction = "UMAP", label = TRUE)

ht <- CellCorHeatmap(
  srt_query = pancreas_sub, srt_ref = panc8_rename,
  query_group = "SubCellType", ref_group = "celltype",
  nlabel = 3, label_by = "row",
  show_row_names = TRUE, show_column_names = TRUE
)
print(ht$plot)

PAGA analysis

pancreas_sub <- RunPAGA(
  srt = pancreas_sub, group_by = "SubCellType",
  linear_reduction = "PCA", nonlinear_reduction = "UMAP"
)
PAGAPlot(srt = pancreas_sub, reduction = "UMAP", label = TRUE, label_insitu = TRUE, label_repel = TRUE)

Velocity analysis

pancreas_sub <- RunSCVELO(
  srt = pancreas_sub, group_by = "SubCellType",
  linear_reduction = "PCA", nonlinear_reduction = "UMAP"
)
#> M-series MacBook detected: Applying M-series specific configurations
#> NUMBA configured for M-series MacBook
#> Using basis: UMAP
#> Renamed 'UMAP' to convention 'X_UMAP' (adata.obsm).
#> Filtered out 12123 genes that are detected 30 counts (shared).
#> Normalized count data: X, spliced, unspliced.
#> Logarithmized X.
#> computing neighbors
#>     finished (0:00:00) --> added 
#>     'distances' and 'connectivities', weighted adjacency matrices (adata.obsp)
#> computing moments based on connectivities
#>     finished (0:00:00) --> added 
#>     'Ms' and 'Mu', moments of un/spliced abundances (adata.layers)
#> computing velocities
#>     finished (0:00:00) --> added 
#>     'stochastic', velocity vectors for each individual cell (adata.layers)
#> computing velocity graph (using 1/16 cores)
#> WARNING: Unable to create progress bar. Consider installing `tqdm` as `pip install tqdm` and `ipywidgets` as `pip install ipywidgets`,
#> or disable the progress bar using `show_progress_bar=False`.
#>     finished (0:00:00) --> added 
#>     'stochastic_graph', sparse matrix with cosine correlations (adata.uns)
#> computing velocity embedding
#>     finished (0:00:00) --> added
#>     'stochastic_UMAP', embedded velocity vectors (adata.obsm)
#> --> added 'stochastic_length' (adata.obs)
#> --> added 'stochastic_confidence' (adata.obs)
#> --> added 'stochastic_confidence_transition' (adata.obs)
#> computing terminal states
#>     identified 0 region of root cells and 1 region of end points .
#>     finished (0:00:00) --> added
#>     'root_cells', root cells of Markov diffusion process (adata.obs)
#>     'end_points', end points of Markov diffusion process (adata.obs)
#> computing terminal states
#>     identified 0 region of root cells and 1 region of end points .
#>     finished (0:00:00) --> added
#>     'root_cells', root cells of Markov diffusion process (adata.obs)
#>     'end_points', end points of Markov diffusion process (adata.obs)
#> computing terminal states
#>     identified 0 region of root cells and 1 region of end points .
#>     finished (0:00:00) --> added
#>     'root_cells', root cells of Markov diffusion process (adata.obs)
#>     'end_points', end points of Markov diffusion process (adata.obs)
#> running PAGA using priors: ['stochastic_root_cells', 'stochastic_end_points']
#> Note: PAGA analysis skipped due to known compatibility issue with scvelo 0.3.x and igraph.
#> This is a known bug (scvelo issue #1241). The velocity analysis continues without PAGA.
VelocityPlot(srt = pancreas_sub, reduction = "UMAP", group_by = "SubCellType")

VelocityPlot(srt = pancreas_sub, reduction = "UMAP", plot_type = "stream")

add: loom file loading?

Differential Expression

pancreas_sub <- RunDEtest(srt = pancreas_sub, group_by = "CellType", fc.threshold = 1, only.pos = FALSE)
#>   |                                                                              |                                                                      |   0%  |                                                                              |==============                                                        |  20%  |                                                                              |============================                                          |  40%  |                                                                              |==========================================                            |  60%  |                                                                              |========================================================              |  80%  |                                                                              |======================================================================| 100%
VolcanoPlot(srt = pancreas_sub, group_by = "CellType")

DEGs <- pancreas_sub@tools$DEtest_CellType$AllMarkers_wilcox
DEGs <- DEGs[with(DEGs, avg_log2FC > 1 & p_val_adj < 0.05), ]
# Annotate features with transcription factors and surface proteins
pancreas_sub <- AnnotateFeatures(pancreas_sub, species = "Mus_musculus", db = c("TF", "CSPA"))
ht <- FeatureHeatmap(
  srt = pancreas_sub, group.by = "CellType", features = DEGs$gene, feature_split = DEGs$group1,
  species = "Mus_musculus", db = c("GO_BP", "KEGG", "WikiPathway"), anno_terms = TRUE,
  feature_annotation = c("TF", "CSPA"), feature_annotation_palcolor = list(c("gold", "steelblue"), c("forestgreen")),
  height = 5, width = 4
)
#>   |                                                                              |                                                                      |   0%  |                                                                              |======================================================================| 100%
print(ht$plot)

Enrichment analysis (over-representation)

pancreas_sub <- RunEnrichment(
  srt = pancreas_sub, group_by = "CellType", db = "GO_BP", species = "Mus_musculus",
  DE_threshold = "avg_log2FC > log2(1.5) & p_val_adj < 0.05"
)
#>   |                                                                              |                                                                      |   0%  |                                                                              |==============                                                        |  20%  |                                                                              |============================                                          |  40%  |                                                                              |==========================================                            |  60%  |                                                                              |========================================================              |  80%  |                                                                              |======================================================================| 100%
EnrichmentPlot(
  srt = pancreas_sub, group_by = "CellType", group_use = c("Ductal", "Endocrine"),
  plot_type = "bar"
)

EnrichmentPlot(
  srt = pancreas_sub, group_by = "CellType", group_use = c("Ductal", "Endocrine"),
  plot_type = "wordcloud"
)

EnrichmentPlot(
  srt = pancreas_sub, group_by = "CellType", group_use = c("Ductal", "Endocrine"),
  plot_type = "wordcloud", word_type = "feature"
)

EnrichmentPlot(
  srt = pancreas_sub, group_by = "CellType", group_use = "Ductal",
  plot_type = "network"
)

EnrichmentPlot(
  srt = pancreas_sub, group_by = "CellType", group_use = "Ductal",
  plot_type = "enrichmap"
)

EnrichmentPlot(srt = pancreas_sub, group_by = "CellType", plot_type = "comparison")

Enrichment analysis (GSEA)

pancreas_sub <- RunGSEA(
  srt = pancreas_sub, group_by = "CellType", db = "GO_BP", species = "Mus_musculus"
)
#>   |                                                                              |                                                                      |   0%
#>   |                                                                              |==============                                                        |  20%
#>   |                                                                              |============================                                          |  40%
#>   |                                                                              |==========================================                            |  60%
#>   |                                                                              |========================================================              |  80%
#>   |                                                                              |======================================================================| 100%
GSEAPlot(
  srt = pancreas_sub, group_by = "CellType", group_use = "Endocrine", plot_type = "bar",
  direction = "both", topTerm = 20
)

GSEAPlot(srt = pancreas_sub, group_by = "CellType", plot_type = "comparison")

Trajectory inference

pancreas_sub <- RunSlingshot(srt = pancreas_sub, group.by = "SubCellType", reduction = "UMAP")

FeatureDimPlot(pancreas_sub, features = paste0("Lineage", 1:3), reduction = "UMAP", theme_use = "theme_blank")

CellDimPlot(pancreas_sub, group.by = "SubCellType", reduction = "UMAP", lineages = paste0("Lineage", 1:3), lineages_span = 0.1)

Dynamic features

pancreas_sub <- RunDynamicFeatures(srt = pancreas_sub, lineages = c("Lineage1", "Lineage2"), n_candidates = 200)
#>   |                                                                              |                                                                      |   0%  |                                                                              |=                                                                     |   2%  |                                                                              |=======                                                               |   9%  |                                                                              |============                                                          |  17%  |                                                                              |=================                                                     |  24%  |                                                                              |======================                                                |  32%  |                                                                              |============================                                          |  40%  |                                                                              |=================================                                     |  47%  |                                                                              |======================================                                |  55%  |                                                                              |============================================                          |  62%  |                                                                              |=================================================                     |  70%  |                                                                              |======================================================                |  77%  |                                                                              |===========================================================           |  85%  |                                                                              |=================================================================     |  92%  |                                                                              |======================================================================| 100%
#>   |                                                                              |                                                                      |   0%  |                                                                              |=                                                                     |   2%  |                                                                              |=======                                                               |   9%  |                                                                              |============                                                          |  17%  |                                                                              |=================                                                     |  24%  |                                                                              |======================                                                |  32%  |                                                                              |============================                                          |  40%  |                                                                              |=================================                                     |  47%  |                                                                              |======================================                                |  55%  |                                                                              |============================================                          |  62%  |                                                                              |=================================================                     |  70%  |                                                                              |======================================================                |  77%  |                                                                              |===========================================================           |  85%  |                                                                              |=================================================================     |  92%  |                                                                              |======================================================================| 100%
pancreas_sub <- AnnotateFeatures(pancreas_sub, species = "Mus_musculus",
  db = c("TF", "CSPA"))
ht <- DynamicHeatmap(
  srt = pancreas_sub, lineages = c("Lineage1", "Lineage2"),
  use_fitted = TRUE, n_split = 6, reverse_ht = "Lineage1",
  species = "Mus_musculus", db = "GO_BP", anno_terms = TRUE, anno_keys = TRUE, anno_features = TRUE,
  heatmap_palette = "viridis", cell_annotation = "SubCellType",
  separate_annotation = list("SubCellType", c("Nnat", "Irx1")), separate_annotation_palette = c("Paired", "Set1"),
  feature_annotation = c("TF", "CSPA"), feature_annotation_palcolor = list(c("gold", "steelblue"), c("forestgreen")),
  pseudotime_label = 25, pseudotime_label_color = "red",
  height = 5, width = 2
)
#>   |                                                                              |                                                                      |   0%  |                                                                              |============                                                          |  17%  |                                                                              |=======================                                               |  33%  |                                                                              |===================================                                   |  50%  |                                                                              |===============================================                       |  67%  |                                                                              |==========================================================            |  83%  |                                                                              |======================================================================| 100%
print(ht$plot)

DynamicPlot(
  srt = pancreas_sub, lineages = c("Lineage1", "Lineage2"), group.by = "SubCellType",
  features = c("Plk1", "Hes1", "Neurod2", "Ghrl", "Gcg", "Ins2"),
  compare_lineages = TRUE, compare_features = FALSE
)

FeatureStatPlot(
  srt = pancreas_sub, group.by = "SubCellType", bg.by = "CellType",
  stat.by = c("Sox9", "Neurod2", "Isl1", "Rbp4"), add_box = TRUE,
  comparisons = list(
    c("Ductal", "Ngn3 low EP"),
    c("Ngn3 high EP", "Pre-endocrine"),
    c("Alpha", "Beta")
  )
)

Interactive data visualization with SCExplorer

PrepareSCExplorer(list(mouse_pancreas = pancreas_sub, human_pancreas = panc8_sub), base_dir = "./SCExplorer")
app <- RunSCExplorer(base_dir = "./SCExplorer")
list.files("./SCExplorer") # This directory can be used as site directory for Shiny Server.
#> [1] "app.R"      "Data.hdf5"  "Meta.hdf5"  "Rplots.pdf"

if (interactive()) {
  shiny::runApp(app)
}

Troubleshooting

Python Environment Issues

# Remove and recreate environment
RemoveEnv()
PrepareEnv(force = TRUE, extras = "all")

# Verify installation
library(SCPNext)
use_uv_env()
reticulate::py_config()
reticulate::py_module_available("scanpy")

Adding Python Dependencies Later

# Install individual packages to existing environment
uv_install(packages = "scvelo")

# Or upgrade from basic to all
uv_install(extras = "all")

# Or reinstall with different extras
PrepareEnv(extras = "all", update = TRUE)

Session Info

sessionInfo()
#> R version 4.5.1 (2025-06-13)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Tahoe 26.0.1
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib 
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
#> 
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#> 
#> time zone: America/Chicago
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] rlang_1.1.6         ggplot2_4.0.0       BiocParallel_1.42.2
#> [4] promises_1.4.0      bslib_0.9.0         shiny_1.11.1       
#> [7] styler_1.11.0       future_1.67.0       SCPNext_0.1.0      
#> 
#> loaded via a namespace (and not attached):
#>   [1] IRanges_2.42.0              R.methodsS3_1.8.2          
#>   [3] dichromat_2.0-0.1           progress_1.2.3             
#>   [5] goftest_1.2-3               Biostrings_2.76.0          
#>   [7] HDF5Array_1.36.0            vctrs_0.6.5                
#>   [9] ggtangle_0.0.7              spatstat.random_3.4-2      
#>  [11] proxy_0.4-27                digest_0.6.37              
#>  [13] png_0.1-8                   shape_1.4.6.1              
#>  [15] slingshot_2.16.0            ggrepel_0.9.6              
#>  [17] deldir_2.0-4                parallelly_1.45.1          
#>  [19] magick_2.9.0                MASS_7.3-65                
#>  [21] reshape2_1.4.4              httpuv_1.6.16              
#>  [23] foreach_1.5.2               BiocGenerics_0.54.1        
#>  [25] qvalue_2.40.0               withr_3.0.2                
#>  [27] xfun_0.53                   ggfun_0.2.0                
#>  [29] ggpubr_0.6.2                survival_3.8-3             
#>  [31] commonmark_2.0.0            memoise_2.0.1              
#>  [33] proxyC_0.5.2                ggbeeswarm_0.7.2           
#>  [35] clusterProfiler_4.16.0      gson_0.1.0                 
#>  [37] princurve_2.1.6             systemfonts_1.3.1          
#>  [39] ragg_1.5.0                  simplifyEnrichment_2.2.0   
#>  [41] tidytree_0.4.6              zoo_1.8-14                 
#>  [43] GlobalOptions_0.1.2         pbapply_1.7-4              
#>  [45] R.oo_1.27.1                 Formula_1.2-5              
#>  [47] prettyunits_1.2.0           KEGGREST_1.48.1            
#>  [49] scatterplot3d_0.3-44        otel_0.2.0                 
#>  [51] httr_1.4.7                  rstatix_0.7.3              
#>  [53] restfulr_0.0.16             globals_0.18.0             
#>  [55] fitdistrplus_1.2-4          rhdf5filters_1.20.0        
#>  [57] rhdf5_2.52.1                UCSC.utils_1.4.0           
#>  [59] miniUI_0.1.2                generics_0.1.4             
#>  [61] DOSE_4.2.0                  curl_7.0.0                 
#>  [63] S4Vectors_0.46.0            ScaledMatrix_1.16.0        
#>  [65] h5mread_1.0.1               polyclip_1.10-7            
#>  [67] GenomeInfoDbData_1.2.14     SparseArray_1.8.1          
#>  [69] xtable_1.8-4                stringr_1.5.2              
#>  [71] doParallel_1.0.17           evaluate_1.0.5             
#>  [73] S4Arrays_1.8.1              BiocFileCache_2.16.2       
#>  [75] hms_1.1.4                   GenomicRanges_1.60.0       
#>  [77] ggwordcloud_0.6.2           irlba_2.3.5.1              
#>  [79] colorspace_2.1-2            filelock_1.0.3             
#>  [81] NLP_0.3-2                   ROCR_1.0-11                
#>  [83] reticulate_1.43.0           spatstat.data_3.1-9        
#>  [85] magrittr_2.0.4              lmtest_0.9-40              
#>  [87] later_1.4.4                 viridis_0.6.5              
#>  [89] ggtree_3.16.3               lattice_0.22-7             
#>  [91] spatstat.geom_3.6-0         future.apply_1.20.0        
#>  [93] scattermore_1.2             XML_3.99-0.19              
#>  [95] scuttle_1.18.0              cowplot_1.2.0              
#>  [97] matrixStats_1.5.0           RcppAnnoy_0.0.22           
#>  [99] ggupset_0.4.1               class_7.3-23               
#> [101] pillar_1.11.1               nlme_3.1-168               
#> [103] iterators_1.0.14            compiler_4.5.1             
#> [105] beachmat_2.24.0             RSpectra_0.16-2            
#> [107] stringi_1.8.7               tensor_1.5.1               
#> [109] SummarizedExperiment_1.38.1 GenomicAlignments_1.44.0   
#> [111] plyr_1.8.9                  crayon_1.5.3               
#> [113] abind_1.4-8                 BiocIO_1.18.0              
#> [115] scater_1.36.0               gridGraphics_0.5-1         
#> [117] locfit_1.5-9.12             sp_2.2-0                   
#> [119] bit_4.6.0                   dplyr_1.1.4                
#> [121] fastmatch_1.1-6             textshaping_1.0.4          
#> [123] codetools_0.2-20            BiocSingular_1.24.0        
#> [125] crosstalk_1.2.2             slam_0.1-55                
#> [127] e1071_1.7-16                GetoptLong_1.0.5           
#> [129] tm_0.7-16                   plotly_4.11.0              
#> [131] mime_0.13                   metR_0.18.2                
#> [133] splines_4.5.1               markdown_2.0               
#> [135] circlize_0.4.16             Rcpp_1.1.0                 
#> [137] fastDummies_1.7.5           sparseMatrixStats_1.20.0   
#> [139] dbplyr_2.5.1                gridtext_0.1.5             
#> [141] knitr_1.50                  blob_1.2.4                 
#> [143] clue_0.3-66                 fs_1.6.6                   
#> [145] checkmate_2.3.3             listenv_0.9.1              
#> [147] DelayedMatrixStats_1.30.0   ggsignif_0.6.4             
#> [149] ggplotify_0.1.3             tibble_3.3.0               
#> [151] Matrix_1.7-4                statmod_1.5.1              
#> [153] tweenr_2.0.3                pkgconfig_2.0.3            
#> [155] tools_4.5.1                 cachem_1.1.0               
#> [157] R.cache_0.17.0              RSQLite_2.4.3              
#> [159] viridisLite_0.4.2           DBI_1.2.3                  
#> [161] scDblFinder_1.22.0          fastmap_1.2.0              
#> [163] rmarkdown_2.30              scales_1.4.0               
#> [165] grid_4.5.1                  ica_1.0-3                  
#> [167] Seurat_5.3.0                Rsamtools_2.24.1           
#> [169] broom_1.0.10                sass_0.4.10                
#> [171] patchwork_1.3.2             FNN_1.1.4.1                
#> [173] Polychrome_1.5.4            dotCall64_1.2              
#> [175] carData_3.0-5               fontawesome_0.5.3          
#> [177] RANN_2.6.2                  farver_2.1.2               
#> [179] mgcv_1.9-3                  yaml_2.3.10                
#> [181] MatrixGenerics_1.20.0       rtracklayer_1.68.0         
#> [183] cli_3.6.5                   purrr_1.1.0                
#> [185] stats4_4.5.1                lifecycle_1.0.4            
#> [187] uwot_0.2.3                  Biobase_2.68.0             
#> [189] backports_1.5.0             bluster_1.18.0             
#> [191] gtable_0.3.6                rjson_0.2.23               
#> [193] ggridges_0.5.7              progressr_0.17.0           
#> [195] parallel_4.5.1              ape_5.8-1                  
#> [197] limma_3.64.3                jsonlite_2.0.0             
#> [199] edgeR_4.6.3                 RcppHNSW_0.6.0             
#> [201] bitops_1.0-9                bit64_4.6.0-1              
#> [203] xgboost_1.7.11.1            Rtsne_0.17                 
#> [205] yulab.utils_0.2.1           litedown_0.7               
#> [207] spatstat.utils_3.2-0        BiocNeighbors_2.2.0        
#> [209] SeuratObject_5.2.0          intrinsicDimension_1.2.0   
#> [211] RcppParallel_5.1.11-1       jquerylib_0.1.4            
#> [213] metapod_1.16.0              GOSemSim_2.34.0            
#> [215] dqrng_0.4.1                 spatstat.univar_3.1-4      
#> [217] R.utils_2.13.0              lazyeval_0.2.2             
#> [219] htmltools_0.5.8.1           enrichplot_1.28.4          
#> [221] GO.db_3.21.0                sctransform_0.4.2          
#> [223] rappdirs_0.3.3              glue_1.8.0                 
#> [225] spam_2.11-1                 httr2_1.2.1                
#> [227] XVector_0.48.0              RCurl_1.98-1.17            
#> [229] treeio_1.32.0               scran_1.36.0               
#> [231] gridExtra_2.3               TrajectoryUtils_1.16.1     
#> [233] igraph_2.2.0                R6_2.6.1                   
#> [235] tidyr_1.3.1                 SingleCellExperiment_1.30.1
#> [237] labeling_0.4.3              cluster_2.1.8.1            
#> [239] Rhdf5lib_1.30.0             yaImpute_1.0-34.1          
#> [241] aplot_0.2.9                 GenomeInfoDb_1.44.3        
#> [243] DelayedArray_0.34.1         tidyselect_1.2.1           
#> [245] vipor_0.4.7                 ggforce_0.5.0              
#> [247] xml2_1.4.0                  car_3.1-3                  
#> [249] AnnotationDbi_1.70.0        rsvd_1.0.5                 
#> [251] KernSmooth_2.23-26          S7_0.2.0                   
#> [253] data.table_1.17.8           htmlwidgets_1.6.4          
#> [255] fgsea_1.34.2                ComplexHeatmap_2.24.1      
#> [257] RColorBrewer_1.1-3          biomaRt_2.64.0             
#> [259] spatstat.sparse_3.1-0       spatstat.explore_3.5-3     
#> [261] simona_1.6.0                ggnewscale_0.5.2           
#> [263] Cairo_1.6-5                 beeswarm_0.4.0